<?php
namespace mvc\web;

class Model
{
    /* @var $db Db */
    public $db;
    public $errors = [];
    public $validators = [
        'required',
        'string',
        'unique',
        'date',
        'int'
    ];

    public function __construct()
    {
        $this->db = Application::getComponent('db');
        $this->db->open();
    }

    public static function tableName(){}

    public function rules(){}

    public function labels(){}

    public function where($where)
    {
        $this->db->where($where);
        return $this;
    }

    public function select($select)
    {
        $this->db->select($select);
        return $this;
    }

    public function limit($limit)
    {
        $this->db->limit($limit);
        return $this;
    }

    public function orderBy($orderBy)
    {
        $this->db->orderBy($orderBy);
        return $this;
    }

    public function one()
    {
        $this->db->from(static::tableName());
        return $this->db->one();
    }

    public function all()
    {
        $this->db->from(static::tableName());
        return $this->db->all();
    }

    public function insert($data)
    {
        $this->validate($data);

        if (!empty(array_filter($this->errors))) {
            return false;
        }
        
        return $this->db->insert(static::tableName(), $data);
    }

    public function update($data)
    {
        $this->validate($data);
        if (!empty(array_filter($this->errors))) {
            return false;
        }
        return $this->db->update(static::tableName(), $data);
    }

    public function delete()
    {
        return $this->db->delete(static::tableName());
    }

    public function count()
    {
        return $this->db->count(static::tableName());
    }
    
    public function groupBy($groupBy)
    {
        $this->db->groupBy($groupBy);
        return $this;
    }

    public function join($tableName, $join, $joinType='left join')
    {
        $this->db->join($tableName, $join, $joinType);
        return $this;
    }
    
    public function validate($data)
    {
        $rules = $this->rules();
        foreach ($data as $key => $value) {
            if (empty($rules[$key])) {
                continue;
            }
            $validates = $rules[$key];
            foreach ($validates as $validate) {
                if (!is_array($validate)) {
                    if($validate == null || !in_array($validate, $this->validators)) {
                        throw new \Exception($validate . '验证器非法');
                    }

                    $validatorName = 'mvc\validator\\' . ucfirst($validate) . 'Validator';

                    $validator = new $validatorName($this, $key, $value);

                    if (!$validator->validate()) {
                        $this->errors[$key] = $validator->getMessage();
                        break;
                    }
                } else {
                    if(!isset($validate[0]) || $validate[0] == null || !in_array($validate[0], $this->validators)) {
                        throw new \Exception('验证器非法');
                    }

                    $validatorName = 'mvc\validator\\' . ucfirst($validate[0]) . 'Validator';

                    $validator = new $validatorName($this, $key, $value);

                    unset($validate[0]);
                    foreach ($validate as $property => $propertyValue) {
                        $validator->$property = $propertyValue;
                    }

                    if (!$validator->validate()) {
                        $this->errors[$key] = $validator->getMessage();
                        break;
                    }
                }
            }
        }
    }

    public function getErrors()
    {
        return $this->errors;
    }

    public function getHeadError()
    {
        $errors = array_filter($this->getErrors());
        if($errors) {
            return $errors[array_keys($errors)[0]];
        }
    }
}
